/**
 * Snowflake ID Generator
 * 
 * A snowflake ID is a 64-bit ID with the following structure:
 * - 1 bit: unused (always 0)
 * - 41 bits: timestamp in milliseconds since epoch or custom epoch
 * - 10 bits: machine ID (we use a random number here)
 * - 12 bits: sequence number within the same millisecond
 * 
 * This implementation is simplified and adapted for browser use.
 */

// Generate a random machine ID at startup (10 bits number, 0-1023)
const MACHINE_ID = Math.floor(Math.random() * 1024);

// Custom epoch (January 1, 2023)
const CUSTOM_EPOCH = 1672531200000;

// Last timestamp used
let lastTimestamp = -1;

// Sequence counter
let sequence = 0;

/**
 * Generate a new snowflake ID
 * @returns String representation of the snowflake ID
 */
export function generateSnowflakeId(): string {
  let timestamp = Date.now();
  
  // If clock moved backwards, throw an exception
  if (timestamp < lastTimestamp) {
    throw new Error('Clock moved backwards. Refusing to generate ID.');
  }
  
  // If same timestamp, increment sequence
  if (timestamp === lastTimestamp) {
    sequence = (sequence + 1) & 4095; // 4095 is the max value of 12 bits
    
    // If sequence overflows, wait for next millisecond
    if (sequence === 0) {
      timestamp = waitNextMillis(lastTimestamp);
    }
  } else {
    // Reset sequence for new timestamp
    sequence = 0;
  }
  
  lastTimestamp = timestamp;
  
  // Calculate snowflake ID
  const timeDiff = timestamp - CUSTOM_EPOCH;
  
  // Construct the ID
  // shift left 22 bits (10 for machine id + 12 for sequence)
  const id = (BigInt(timeDiff) << 22n) |
            // machine id - shift left 12 bits
            (BigInt(MACHINE_ID) << 12n) |
            // sequence - no shift needed
            BigInt(sequence);
  
  return id.toString();
}

/**
 * Wait until next millisecond
 */
function waitNextMillis(lastTimestamp: number): number {
  let timestamp = Date.now();
  while (timestamp <= lastTimestamp) {
    timestamp = Date.now();
  }
  return timestamp;
}